<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>分片上传文件</title>
    <!-- 使用本地路径 -->
    <script src="/js/spark-md5.min.js"></script>
</head>
<body>

<form id="uploadForm">
    文件: <input type="file" id="file" name="file" required><br>
    <progress id="progressBar" value="0" max="100" style="width: 300px;"></progress>
    <p id="status"></p>
    <button type="submit">提交</button>
</form>

<script>
    const chunkSize = 2 * 1024 * 1024; // 2MB 每片

    document.getElementById("uploadForm").onsubmit = async function(event) {
        event.preventDefault();

        const fileInput = document.getElementById("file");
        const file = fileInput.files[0];
        if (!file) {
            alert("请选择文件！");
            return;
        }

        const totalChunks = Math.ceil(file.size / chunkSize);
        let uploadedChunks = 0;

        for (let chunkNumber = 1; chunkNumber <= totalChunks; chunkNumber++) {
            const start = (chunkNumber - 1) * chunkSize;
            const end = Math.min(start + chunkSize, file.size);
            const chunk = file.slice(start, end);

            const md5 = await calculateMd5(chunk);
            const formData = new FormData();
            formData.append("file", chunk, file.name);
            formData.append("md5", md5);
            formData.append("chunkNumber", chunkNumber);
            formData.append("totalChunks", totalChunks);

            try {
                await uploadChunk(formData);
                uploadedChunks++;
                updateProgress(uploadedChunks, totalChunks);
            } catch (error) {
                console.error("上传分片失败:", error);
                document.getElementById("status").innerText = "上传失败，请重试";
                return;
            }
        }

        document.getElementById("status").innerText = "所有分片上传完成，正在合并文件";
    };

    function calculateMd5(blob) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsBinaryString(blob);
            reader.onloadend = function () {
                const md5 = SparkMD5.hashBinary(reader.result);
                resolve(md5);
            };
            reader.onerror = function (error) {
                reject(error);
            };
        });
    }

    function uploadChunk(formData) {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            xhr.open("POST", "/upload", true);
            xhr.onload = function() {
                if (xhr.status === 200) {
                    resolve(xhr.responseText);
                } else {
                    reject(new Error("上传失败，错误代码：" + xhr.status));
                }
            };
            xhr.onerror = function() {
                reject(new Error("网络错误"));
            };
            xhr.send(formData);
        });
    }

    function updateProgress(uploadedChunks, totalChunks) {
        const percentComplete = Math.round((uploadedChunks / totalChunks) * 100);
        document.getElementById("progressBar").value = percentComplete;
        document.getElementById("status").innerText = "上传进度: " + percentComplete + "%";
    }
</script>

</body>
</html>
